package org.flixel 
{
	import flash.net.FileFilter;
	import flash.utils.ByteArray;
	import org.flixel.FlxG;
	import org.flixel.FlxTilemap;
	import org.flixel.FlxU;


	public class FlxTilemapExt extends FlxTilemap
	{
		
		public function loadOgmoTileMap(Level:XML, MapLayer:String, TileGraphics:Class):FlxTilemapExt
		{
			_pixels = FlxG.addBitmap(TileGraphics);
			
			var xml:XML = Level;
			//FlxG.log( Level);
			_tileWidth = xml.descendants(MapLayer).@tileWidth;
			_tileHeight = xml.descendants(MapLayer).@tileHeight;
			
			widthInTiles = xml.width / _tileWidth;
			heightInTiles = xml.height / _tileHeight;
			
			totalTiles = widthInTiles * heightInTiles;
			
			width = xml.width;
			height = xml.height;
			
			_block.width = _tileWidth;
			_block.height = _tileHeight;
			
			// Quad tree tweaks
			FlxU.setWorldBounds(0, 0, width, height, 3);
			
			// Initialize the data
			_data = new Array();
			for(var di:int; di < totalTiles; di++)
				_data.push(0);
			
			totalTiles = widthInTiles * heightInTiles;
			_rects = new Array(totalTiles);
			
			// Set tiles
			var i:XML;
			for each(i in xml.descendants(MapLayer)[0].tile)
			{
				this.setTile((i.@x / _tileWidth), (i.@y / _tileHeight), i.@id);
			}
			for each(i in xml.descendants(MapLayer)[0].rect)
			{
				var startTileX:int = i.@x / _tileWidth;
				var endTileX:int = startTileX + (i.@w / _tileWidth);
				var startTileY:int = i.@y / _tileHeight;
				var endTileY:int = startTileY + (i.@h / _tileHeight);
				
				for (var xTile:int = startTileX; xTile < endTileX; xTile++)
				{
					for (var yTile:int = startTileY; yTile < endTileY; yTile++)
					{
						this.setTile(xTile, yTile, i.@id);
					}
				}
			}
			
			// Update screen vars
			_screenRows = Math.ceil(FlxG.height / _tileHeight) + 1;
			if(_screenRows > heightInTiles) _screenRows = heightInTiles;
			
			_screenCols = Math.ceil(FlxG.width / _tileWidth) + 1;
			if(_screenCols > widthInTiles) _screenCols = widthInTiles;
			
			// Refresh collision data
			refreshHulls();
			
			return this;
		}
		
		public function loadOgmoObjects(Level:XML, MapLayer:String, ObjectName:String, ObjectType:Class, ObjectGroup:FlxGroup):FlxTilemapExt
		{ 			
			var xml:XML = Level;
			//FlxG.log( Level);
			
			// Set objects
			var i:XML;
			for each(i in xml.descendants(MapLayer).descendants(ObjectName))
			{
				ObjectGroup.add(new ObjectType(i.@x , i.@y));
			}			
			
			// Refresh collision data
			refreshHulls();
			
			return this;
		}
		
		public function loadOgmoMovingObjects(Level:XML, MapLayer:String, ObjectName:String, TileGraphics:Class, objectGroup:FlxGroup,
			ObjectWidth:uint = 15, ObjectHeight:uint = 15):FlxTilemapExt
		{
			_pixels = FlxG.addBitmap(TileGraphics);
			
			var xml:XML = Level;
			//FlxG.log( Level);
			_tileWidth = ObjectWidth;
			_tileHeight = ObjectHeight;
			
			// Set moving objects position and velocities and bounding boxes
			var i:XML;
			for each(i in xml.descendants(MapLayer).descendants(ObjectName))
			{				
				var newObject:MovingObject = new MovingObject(TileGraphics, i.@width, 5);
				newObject.setStartPoint(i.@x, i.@y);
				newObject.setBoundingBox((int)(i.node.@x), i.node.@y);
				newObject.setVelocity(i.@speed, i.@speed);
				objectGroup.add(newObject);	
			}
			
			// Refresh collision data
			refreshHulls();
			
			return this;
		}
		
		public function loadOgmoConveyorBelts(Level:XML, MapLayer:String, ObjectGroup:FlxGroup):FlxTilemapExt
		{ 			
			var xml:XML = Level;
			
			var newBelt:ConveyorBelt;
			
			// Set conveyor belts
			var i:XML;
			for each(i in xml.descendants(MapLayer).leftBelt)
			{
				newBelt = new ConveyorBelt(i.@x, i.@y, 1);
				newBelt.setBeltSpeed(i.@speed);
				ObjectGroup.add(newBelt);
				this.setTile((i.@x / _tileWidth), (i.@y / _tileHeight), 100, false);
			}		
			
			for each(i in xml.descendants(MapLayer).centerBelt)
			{
				var beltWidth:int = i.@width;
				var totalTiles:int = beltWidth / 15;
				
				for (var tileNumber:int = 0; tileNumber < totalTiles; tileNumber++)
				{
					newBelt = new ConveyorBelt((int)(i.@x) + (tileNumber * 15), i.@y, 2);
					newBelt.setBeltSpeed(i.@speed);
					ObjectGroup.add(newBelt);
					this.setTile((((int)(i.@x) + (tileNumber * 15)) / _tileWidth), (i.@y / _tileHeight), 100, false);
				}
			}
			
			for each(i in xml.descendants(MapLayer).rightBelt)
			{
				newBelt = new ConveyorBelt(i.@x , i.@y, 3);
				newBelt.setBeltSpeed(i.@speed);
				ObjectGroup.add(newBelt);
				this.setTile((i.@x / _tileWidth), (i.@y / _tileHeight), 100, false);
			}
			
			// Refresh collision data
			refreshHulls();
			
			return this;
		}
		
		public function loadOgmoCollision(Level:String, TileGraphics:Class):FlxTilemapExt
		{
			//var file:ByteArray = new Level;
			//var str:String = file.readUTFBytes(file.length);
			//var xml:XML = new XML(file);
			
			// Figure out the map dimensions
			_tileWidth = 32;
			_tileHeight = 32;
			
			// Convert Ogmo data to CSV
			var mapData:String = Level;
			var rows:Array = mapData.split("\n");
			
			var out:String = "";
			
			for(var i:uint = 0; i < rows.length; i++)
			{
				var l:uint = rows[i].length;
				var c:uint = 0;
				
				for(var j:uint = 0; j < l; j++)
				{
					out += rows[i].charAt(j);
					c++;
					if(c < l)
						out += ",";
				}
				
				out += "\n";
			}
			
			// ... and do it the classic way :)
			this.loadMap(out, TileGraphics, _tileWidth, _tileHeight);
			
			return this;
		}
	}

}